package com.atguigu.daijia.dispatch.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.daijia.common.constant.RedisConstant;
import com.atguigu.daijia.dispatch.mapper.OrderJobMapper;
import com.atguigu.daijia.dispatch.service.NewOrderService;
import com.atguigu.daijia.dispatch.xxl.client.XxlJobClient;
import com.atguigu.daijia.map.client.LocationFeignClient;
import com.atguigu.daijia.model.entity.dispatch.OrderJob;
import com.atguigu.daijia.model.enums.OrderStatus;
import com.atguigu.daijia.model.form.map.SearchNearByDriverForm;
import com.atguigu.daijia.model.vo.dispatch.NewOrderTaskVo;
import com.atguigu.daijia.model.vo.map.NearByDriverVo;
import com.atguigu.daijia.model.vo.order.NewOrderDataVo;
import com.atguigu.daijia.order.client.OrderInfoFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class NewOrderServiceImpl implements NewOrderService {

    @Autowired
    private OrderJobMapper orderJobMapper;

    @Autowired
    private XxlJobClient xxlJobClient;//任务调度

    @Autowired
    private LocationFeignClient locationFeignClient;

    @Autowired
    private OrderInfoFeignClient orderInfoFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    /*
     * 创建并启动任务调度方法
     * */
    @Override
    public Long addAndStartTask(NewOrderTaskVo newOrderTaskVo) {
        //1.判断当前订单是否已经启动任务调度
        //通过订单id在数据库查询有没有这个订单
        LambdaQueryWrapper<OrderJob> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderJob::getOrderId,newOrderTaskVo.getOrderId());
        OrderJob orderJob = orderJobMapper.selectOne(wrapper);
        //如果没有创建-》创建 如果已经启动，则不管
        if(orderJob == null){
            //没有这个订单的任务调度，开启！
            /*
            * 参数：
            * 1.executorHandler：执行任务的job方法
            * 2.param：相关参数，暂时为空
            * 3.corn：执行的cron表达式，多久执行一次
            * 4.desc：描述信息
            * */
            Long jobId = xxlJobClient.addAndStart("newOrderTaskHandler", "",
                    "0 */1 * * * ?", "新创建订单任务调度：" + newOrderTaskVo.getOrderId());//每一分钟执行一次
            //创建好job了，把orderjob加入数据库保存
            orderJob = new OrderJob();
            orderJob.setOrderId(newOrderTaskVo.getOrderId());
            orderJob.setJobId(jobId);
            orderJob.setParameter(JSONObject.toJSONString(newOrderTaskVo));
            orderJobMapper.insert(orderJob);
        }
        return orderJob.getJobId();
    }

    //搜索附近代驾司机
    @Override
    public void executeTask(long jobId) {
        //根据jobid查询数据库查看当前任务是否已经创建
        LambdaQueryWrapper<OrderJob> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderJob::getJobId,jobId);
        OrderJob orderJob = orderJobMapper.selectOne(wrapper);
        //如果没有创建任务则不需要完成
        if(orderJob == null){
            return;
        }
        //查询当前订单状态，如果订单是接单的状态就继续执行，如果不适接单状态，停止任务调度
        String jsonString = orderJob.getParameter();
        NewOrderTaskVo newOrderTaskVo = JSONObject.parseObject(jsonString, NewOrderTaskVo.class);
        Integer status = orderInfoFeignClient.getOrderStatus(newOrderTaskVo.getOrderId()).getData();
        if(status.intValue() != OrderStatus.WAITING_ACCEPT.getStatus().intValue()){
            //不适接单状态，停止任务调度
            xxlJobClient.stopJob(jobId);
            return;
        }
        //远程调用：搜索附近满足条件可以接单的司机，获取满足可以接单的司机的集合
        SearchNearByDriverForm searchNearByDriverForm = new SearchNearByDriverForm();
        searchNearByDriverForm.setLongitude(newOrderTaskVo.getStartPointLongitude());
        searchNearByDriverForm.setLatitude(newOrderTaskVo.getStartPointLatitude());
        searchNearByDriverForm.setMileageDistance(newOrderTaskVo.getExpectDistance());
        List<NearByDriverVo> nearByDriverVoList = locationFeignClient.searchNearByDriver(searchNearByDriverForm).getData();

        //遍历司机集合，为每个司机创建一个临时队列，存储新订单信息
        for (NearByDriverVo driver : nearByDriverVoList) {
            //使用redis的set（保证推送信息不重复）
            String repeatKey = RedisConstant.DRIVER_ORDER_REPEAT_LIST + newOrderTaskVo.getOrderId();//redis的key
            //记录司机id，防止重复推送
            //把订单推送给满足条件的多个司机
            Boolean ismember = redisTemplate.opsForSet().isMember(repeatKey, driver.getDriverId());
            if (!ismember) {
                redisTemplate.opsForSet().add(repeatKey,driver.getDriverId());
                //设置过期时间，16分钟
                redisTemplate.expire(repeatKey,RedisConstant.DRIVER_ORDER_REPEAT_LIST_EXPIRES_TIME, TimeUnit.MINUTES);
                //新订单保存到司机的临时队列中，redis中的list
                NewOrderDataVo newOrderDataVo = new NewOrderDataVo();
                newOrderDataVo.setOrderId(newOrderTaskVo.getOrderId());
                newOrderDataVo.setStartLocation(newOrderTaskVo.getStartLocation());
                newOrderDataVo.setEndLocation(newOrderTaskVo.getEndLocation());
                newOrderDataVo.setExpectAmount(newOrderTaskVo.getExpectAmount());
                newOrderDataVo.setExpectDistance(newOrderTaskVo.getExpectDistance());
                newOrderDataVo.setExpectTime(newOrderTaskVo.getExpectTime());
                newOrderDataVo.setFavourFee(newOrderTaskVo.getFavourFee());
                newOrderDataVo.setDistance(driver.getDistance());
                newOrderDataVo.setCreateTime(newOrderTaskVo.getCreateTime());
                //根据司机id生成key
                String key = RedisConstant.DRIVER_ORDER_TEMP_LIST + driver.getDriverId();
                redisTemplate.opsForList().leftPush(key,JSONObject.toJSONString(newOrderDataVo));//从头插入
                //设置过期时间1分钟
                redisTemplate.expire(key,RedisConstant.DRIVER_ORDER_TEMP_LIST_EXPIRES_TIME,TimeUnit.MINUTES);
            }

        }
    }

    /*
     * 查询司机最新订单
     * */
    @Override
    public List<NewOrderDataVo> findNewOrderQueueData(Long driverId) {
        List<NewOrderDataVo> list = new ArrayList<>();
        //从司机的临时队列中拿到所有订单
        String key = RedisConstant.DRIVER_ORDER_TEMP_LIST + driverId;//key
        Long size = redisTemplate.opsForList().size(key);
        if(size > 0){
            //有订单才取
            for (int i = 0; i < size; i++) {
                String content = (String) redisTemplate.opsForList().leftPop(key);
                NewOrderDataVo newOrderDataVo = JSONObject.parseObject(content, NewOrderDataVo.class);
                list.add(newOrderDataVo);
            }
        }
        return list;
    }

    /*
     * 清空新订单队列数据
     * */
    @Override
    public Boolean clearNewOrderQueueData(Long driverId) {
        String key = RedisConstant.DRIVER_ORDER_TEMP_LIST + driverId;
        redisTemplate.delete(key);
        return true;
    }
}
